package app.Insam.VNC;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;

import app.Insam.VNC.remote.ConnectionBean;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class InsamConnection {
	public static final String TAG = "InsamApp";
	final static byte MSG_LOGIN = 0x01;
	final static byte MSG_LOGOUT = 0x02;
	int mServer_port=0;
	
	InsamMain mParent;	
	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message _msg) {
			switch(_msg.what) {
			case R.string.text_RequestAuthentication:
				mProgressDlg.setMessage(mParent.getString(_msg.what));
				break;
			case R.string.text_TurnComp:
				mProgressDlg.setMessage(mParent.getString(_msg.what)+String.format(" (%d%%)", _msg.arg1));				
				Message msg = new Message();
				msg.what = R.string.text_TurnComp;
				msg.arg1 = _msg.arg1 + 1;
				if(_msg.arg1==100) {
					mProgressDlg.dismiss();
					mParent.VncStart();
				} else {
					sendMessageDelayed(msg, 100);
				}
				break;
				
			case R.string.text_InvalidID:
			case R.string.text_InvalidPWD:
			case R.string.text_InvalidHost:
			case R.string.text_NotRespond:
				new AlertDialog.Builder(mParent) 
				.setTitle(R.string.Conn_Failure)
				.setMessage(_msg.what)
				.setIcon(android.R.drawable.ic_dialog_alert) 
				.setPositiveButton(android.R.string.ok, null)
				.show();
				break;
			case R.string.text_ServerError:
				new AlertDialog.Builder(mParent) 
				.setTitle(R.string.Conn_Failure)
				.setMessage(mParent.getString(R.string.text_ServerError) + "\nerror code:" + _msg.arg1)
				.setIcon(android.R.drawable.ic_dialog_alert) 
				.setPositiveButton(android.R.string.ok, null)
				.show();				
				break;
			}
		}
	};	
	ProgressDialog mProgressDlg;
	Thread mWorker;
	ConnectionBean mConnInfo;	
	
	InsamConnection(InsamMain _parent, String _ip, int _port) {
		mParent = _parent;			
		mConnInfo = new ConnectionBean(_ip, _port);			
	}
	
	public void ConnectServer(String _uid) {			
		mConnInfo.setNickname(_uid);
		
		if(mConnInfo==null) {
			//예외처리 
			return ;
		}			
		
		mProgressDlg = new ProgressDialog(mParent);
		mProgressDlg.setTitle(R.string.OfficePC_Conn);	
		mProgressDlg.setMessage(mParent.getString(R.string.text_Conn_Server));
		mProgressDlg.setCancelable(false);	
		mProgressDlg.setButton(mParent.getString(android.R.string.cancel), new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface _dialog, int _whichButton) {
				if(mWorker!=null)
					mWorker.stop();
				mHandler.removeMessages(R.string.text_TurnComp);
			}
		});	
		mProgressDlg.show();			
	
		mWorker = new Thread() {
			@Override
			public void run() {		
				try {
					SocketAddress sockaddr = new InetSocketAddress(mConnInfo.getAddress(), mConnInfo.getPort());
					Socket server = new Socket();
					server.connect(sockaddr, 10000);
					mHandler.sendEmptyMessage(R.string.text_RequestAuthentication);
					OutputStream os = server.getOutputStream();					
					/*			
					typedef struct {
					    BYTE uid[UID_LEN];		   -> 10
					    BYTE passwd[PASSWD_LEN];   -> 20
					} REQ_LOGIN;					
					*/	
					
					ByteBuffer bbuf = ByteBuffer.allocate(1+30);
					bbuf.order(ByteOrder.LITTLE_ENDIAN);			
					
					bbuf.put(MSG_LOGIN);			//msg_code
					int des_pos=1;
					
					bbuf.put(mConnInfo.getNickname().getBytes("UTF-8"));							//id
					bbuf.position(des_pos += 10);			
					bbuf.put(mConnInfo.getPassword().getBytes("UTF-8"));	//passwd
					bbuf.position(des_pos += 20);
					
					os.write(bbuf.array());		
					
					InputStream is = server.getInputStream();
		/*			
					typedef struct {
					    BYTE ret[1];           		-> 1
					    BYTE vnc_port[2];			-> 2
					} RES_LOGIN;
		*/			
					byte[] buf = new byte[3];
					is.read(buf);
					os.close();
					is.close();
					server.close();	
					bbuf = ByteBuffer.wrap(buf);
					int ret = bbuf.get();
					if(ret!=1) {				//예외처리!!!		
						if(ret==-2) {
							mHandler.sendEmptyMessage(R.string.text_InvalidID);									
						} else if(ret==-3) {
							mHandler.sendEmptyMessage(R.string.text_InvalidPWD);			
						} else {	
							Message msg = new Message();
							msg.what = R.string.text_ServerError;
							msg.arg1=ret;
							mHandler.sendMessage(msg);				
						}
						mProgressDlg.dismiss();
						return;
					}
					mServer_port = mConnInfo.getPort();
					mConnInfo.setPort(bbuf.getShort());	
					
					Message msg = new Message();
					msg.what = R.string.text_TurnComp;
					msg.arg1=1;
					mHandler.sendMessage(msg);	
				} catch (UnknownHostException e) {		
					mProgressDlg.dismiss();	
					mHandler.sendEmptyMessage(R.string.text_InvalidHost);
				} catch (IOException e) {
					mProgressDlg.dismiss();	
					mHandler.sendEmptyMessage(R.string.text_NotRespond);
				} 
					
			}
		};
		mWorker.setDaemon(true);
		mWorker.start();
	}	
	
	public void Logout() {
		mWorker = new Thread() {
			@Override
			public void run() {		
				try {
					SocketAddress sockaddr = new InetSocketAddress(mConnInfo.getAddress(), mServer_port);
					Socket server = new Socket();
					server.connect(sockaddr, 10000);
					
					OutputStream os = server.getOutputStream();		
					ByteBuffer bbuf = ByteBuffer.allocate(1+10);
					bbuf.order(ByteOrder.LITTLE_ENDIAN);			
					
					bbuf.put(MSG_LOGOUT);									//msg_code			
					bbuf.put(mConnInfo.getNickname().getBytes("UTF-8"));	//id			
					os.write(bbuf.array());		
					os.close();
					server.close();						
				} catch (IOException e) {		
					InsamDebugger.toast(TAG, "Logout Exception:"+e.getMessage());
				}
			}
		};
		mWorker.setDaemon(true);		
		mWorker.start();
		InsamDebugger.toast(TAG, "Send Logout Msg");
	}
	
	public void setPassword(String _pwd) {
		mConnInfo.setPassword(_pwd);
	}

	public ConnectionBean connInfo() {
		return mConnInfo;
	}
}
